/*
 * Funny Language - a free style programming language.
 * Copyright (C) 2015 by fanguangping (fanguangping@163.com)
 * test_string.c
 */

#include <string.h>
#include "runner_ds.h"

static void test_alloc_string() {
	String str = alloc_string(1);
	assert_non_null(str);
}

static void test_alloc_string_array() {
	String *str_arr = alloc_string_array(1);
	assert_non_null(str_arr);
}

static void test_realloc_string() {
	String str = alloc_string(1);
	str = realloc_string(str, 2);
	assert_non_null(str);
}

static void test_init_string() {
	String str = init_string();
	assert_non_null(str);
	assert_int_equal(strlen(str), 0);
}

static void test_copy_string() {
	String src = "abc";
	String dest = copy_string(src);
	assert_non_null(dest);
	assert_string_equal(src, dest);
}

static void test_trim_string() {
	String str = copy_string(" abc ");
	String lstr = copy_string("abc ");
	String rstr = copy_string(" abc");
	String trimed = "abc";
	assert_string_equal(trim_string(str), trimed);
	assert_string_equal(trim_string(lstr), trimed);
	assert_string_equal(trim_string(rstr), trimed);
}

static void test_substr_before() {
	String str = copy_string("aaaaaa[bbbbbb]cccccc");
	String substr = substr_before(str, '[');
	assert_string_equal(substr, "aaaaaa");
}

static void test_substr_between() {
	String str = copy_string("aaaaaa[bbbbbb]cccccc");
	String substr = substr_between(str, '[', ']');
	assert_string_equal(substr, "bbbbbb");
}

static void test_substr_after() {
	String str = copy_string("aaaaaa[bbbbbb]cccccc");
	String substr = substr_after(str, ']');
	assert_string_equal(substr, "cccccc");
}

static void test_dyna_strcat() {
	//TODO strcat null or ""
	String str = copy_string("aaa");
	str = dyna_strcat(str, "bbb");
	assert_string_equal(str, "aaabbb");
}

static void test_append_char() {
	String str = copy_string("aaa");
	str = append_char(str, '1');
	assert_string_equal(str, "aaa1");
}

static void test_split_string() {
	String str = copy_string("aaaaaa|bbbbbb|cccccc");
	String *arr = split_string(str, '|');
	assert_string_equal(arr[0], "aaaaaa");
	assert_string_equal(arr[1], "bbbbbb");
	assert_string_equal(arr[2], "cccccc");
	assert_null(arr[3]);
}

static void test_fetch_string_from_paren_with_escape() {
	String str = copy_string("<real>-<ureal>i");
	String *arr = fetch_string_from_paren_with_escape(str, '<', '>', '\\');
	assert_string_equal(arr[0], "real");
	assert_string_equal(arr[1], "ureal");
	assert_null(arr[2]);
	str = copy_string("<re\\<a\\>l>-<ureal>i");
	arr = fetch_string_from_paren_with_escape(str, '<', '>', '\\');
	assert_string_equal(arr[0], "re\\<a\\>l");
	assert_string_equal(arr[1], "ureal");
	assert_null(arr[2]);
}

static void test_split_string_once() {
	String str = copy_string("aaaaaa|bbbbbb|cccccc");
	String *arr = split_string_once(str, '|');
	assert_string_equal(arr[0], "aaaaaa");
	assert_string_equal(arr[1], "bbbbbb|cccccc");
	assert_null(arr[2]);
}

static void test_equals_string() {
	String str = copy_string("abc");
	assert_true(equals_string(str, "abc"));
	assert_true(equals_string(NULL, NULL));
	assert_false(equals_string(str, NULL));
	assert_false(equals_string(NULL, str));
}

static void test_hash_code_string() {
	String str = copy_string("abc");
	int hashCode = hash_code_string("abc");
	assert_in_range(hashCode, 0, HASHTABLE_SIZE-1);
	assert_int_equal(hash_code_string(str), hashCode);
}

static void test_strlwr() {
	String str = copy_string("AbC");
	assert_string_equal(strlwr(str), "abc");
}

static void test_split_strings_case1() {
	String str = strdup("<bool> :: (lex \"Boolean\" \"$1\")");
	String *r = split_strings(str, " :: ");
	assert_string_equal(r[0], "<bool>");
	assert_string_equal(r[1], "(lex \"Boolean\" \"$1\")");
	assert_null(r[2]);
}

static void test_split_strings_case2() {
	String str = strdup("<bool>");
	String *r = split_strings(str, " :: ");
	assert_string_equal(r[0], "<bool>");
	assert_null(r[1]);
}

int main(int argc, char **argv) {
	const struct CMUnitTest tests[] = {
			cmocka_unit_test(test_alloc_string),
			cmocka_unit_test(test_alloc_string_array),
			cmocka_unit_test(test_realloc_string),
			cmocka_unit_test(test_init_string),
			cmocka_unit_test(test_copy_string),
			cmocka_unit_test(test_trim_string),
			cmocka_unit_test(test_substr_before),
			cmocka_unit_test(test_substr_between),
			cmocka_unit_test(test_substr_after),
			cmocka_unit_test(test_dyna_strcat),
			cmocka_unit_test(test_append_char),
			cmocka_unit_test(test_split_string),
			cmocka_unit_test(test_fetch_string_from_paren_with_escape),
			cmocka_unit_test(test_split_string_once),
			cmocka_unit_test(test_equals_string),
			cmocka_unit_test(test_hash_code_string),
			cmocka_unit_test(test_strlwr),
			cmocka_unit_test(test_split_strings_case1),
			cmocka_unit_test(test_split_strings_case2),
	};
	return cmocka_run_group_tests(tests, NULL, NULL);
}
